#!/bin/bash

# Library of bash functions use by test/*.sh
# The scripts begin "source functions.source"
# Don't detab this file! removeTest() addModTest() need them!

##
# run a test
runTest()
{
    local prog=$1
    shift
    (
        mkdir -p $here/tmp
        cd       $here/tmp
        if [ ! -z $EXIV2_ECHO ]; then
            echoTest $VALGRIND $bin$prog$exe "$@"
        fi
        $VALGRIND $bin$prog$exe "$@"
    )
}

##
# echo commands and arguments
echoTest()
{
    local count=1
    for i in $@ ; do
        echo $((count++)):  $i
    done
    echo -----------------------
}

##
# predictate
existsTest()
{
    local prog=$1
    result=0
    if [ -z "$bin" ]; then
        if [ ! -z $(which $prog) ]; then
            result=1
        fi
    else
        if [ -e $bin$prog -o -e $bin$prog$exe ]; then
            result=1
        fi
    fi
    echo $result
}

##
# copy file (used by conversions.sh)
copy()
{
    \cp "$1" "$2"
}

##
# copy file from data to tmp (copyTestFile from to)
copyTestFile()
{
    if [ $# == 2 ]; then
        cp -f "$here/data/$1" "$here/tmp/$2"
    elif [ $# == 1 ]; then
        stub=$(basename $1)
        cp -f "$here/data/$1" "$here/tmp/$stub"
    else
        echo "*** error copyTestFile: illegal number of inputs = $# ***"
    fi

}

##
# copy 1 or more files from data to tmp
copyTestFiles()
{
    for i in "$@" ; do
        copyTestFile "$i" "$i"
    done
}

##
# result analysis
reportTest()
{
    cat $results | tr '\\' '/' > ${results}-new
    mv -f ${results}-new $results

    if [ $# -eq 0 ]; then
        lhs=$results
        rhs=$good
    else
        if [ $# -eq 3 ] ; then
            diffargs=$1
            lhs=$2
            rhs=$3
        else
            lhs=$1
            rhs=$2
        fi
    fi

    diff $diffargs $lhs $rhs
    rc=$?
    if [ $rc -eq 0 ] ; then
        echo "all testcases passed."
    fi
}

##
# moved here from write-test.sh
# Function:
#     runTestCase number file
# Params:
#     number: Test case number
#     file  : Input file
# Abstract:
# Run the requested test case number with the given file
runTestCase()
{
    rtc_number=$1
    rtc_infile=$2

    rtc_outfile=test${rtc_number}.jpg
    rtc_jpgthumb=thumb${rtc_number}.jpg
    rtc_tifthumb=thumb${rtc_number}.tif

    rm -f $rtc_outfile $rtc_jpgthumb $rtc_tifthumb
    rm -f iii ttt;

    echo "------------------------------------------------------------"
    runTest exifprint $rtc_infile > iii;
    cp $rtc_infile $rtc_outfile;
    runTest write-test $rtc_infile $rtc_number > ttt;
    diff $diffargs iii ttt
}

##
# moved here from imagetest.sh
eraseTest()
{
    src=$1
    test=${src}.etst
    good=$datapath/${src}.egd

    #setup
    cp $datapath/$src $test

    #run tests
    ${bin}metacopy $test $test

    #check results
    diffCheck $test $good
    printf "."
}

copyTest()
{
    num=$1    # case number
    src=$2    # input file
    dst=$3    # copy to hear
    test=${dst}.c${num}tst
    good=$datapath/${dst}.c${num}gd

    #setup
    cp $datapath/$dst $test

    #run tests
    ${bin}metacopy -a $datapath/$src $test

    #check results
    diffCheck $test $good
    printf "."
}

iptcTest()
{
    num=$1    # case number
    src=$2    # input file
    dst=$3    # copy to hear
    test=${dst}.i${num}tst
    good=$datapath/${dst}.i${num}gd

    #setup
    cp $datapath/$dst $test

    #run tests
    runTest metacopy -ip $datapath/$src $test

    #check results
    diffCheck $test $good
    printf "."
}

##
# Make sure to pass the test file first and the known good file second
diffCheck()
{
    test=$(real_path $1)
    good=$(real_path $2)
    if [ -z "$errors" ]; then let -a errors=0; fi

    #run diff and check results
    if [ $PLATFORM == SunOS ]; then
        bdiff $diffargs "$test" "$good"
    elif [ $PLATFORM == FreeBSD -o $PLATFORM == NetBSD ]; then
        diff $diffargs "$test" "$good"
    else
        diff --binary $diffargs "$test" "$good"
    fi
    if [ $? -ne 0 ]; then
       errors=$(expr $errors + 1)
    else
       rm $test
    fi
}

##
# moved here from iotest.sh
ioTest()
{
    src=$datapath/$1
    out1=${1}.1
    out2=${1}.2

    #run tests
    runTest iotest $src $out1 $out2
    if [ $? -ne 0 ]; then
       errors=`expr $errors + 1`
       return
    fi

    #check results
    diffCheck $out1 $src
    diffCheck $out2 $src
    printf "."
}

##
# moved here from iptctest.sh
printTest()
{
    src=$1
    test=${src}.iptst
    good=$datapath/${src}.ipgd

    #run tests
    runTest iptcprint $datapath/$src > $test

    #check results
    diffCheck $test $good
    printf "."
}

removeTest()
{
    src=$1
    tmp="temp"
    test=${src}.irtst
    good=$datapath/${src}.irgd

    #setup
    cp $datapath/$src $tmp

    #run tests
    runTest iptctest $tmp <<-eoc
		r Iptc.Application2.Byline
		r Iptc.Application2.Caption
		r Iptc.Application2.Keywords
		r Iptc.Application2.Keywords
		r Iptc.Application2.Keywords
		r Iptc.Application2.CountryName
eoc
    runTest iptcprint $tmp > $test

    #check results
    diffCheck $test $good
    printf "."
    rm $tmp
}

addModTest()
{
    src=$1
    tmp="temp"
    test=${src}.iatst
    good=$datapath/${src}.iagd

    #setup
    cp $datapath/$src $tmp

    #run tests
    runTest iptctest $tmp <<-eoc
		a Iptc.Application2.Headline		  The headline I am
		a Iptc.Application2.Keywords		  Yet another keyword
		m Iptc.Application2.DateCreated		  2004-8-3
		a Iptc.Application2.Urgency			  3
		m Iptc.Application2.SuppCategory	  "bla bla ba"
		a Iptc.Envelope.ModelVersion		  2
		a Iptc.Envelope.TimeSent			  14:41:0-05:00
		a Iptc.Application2.RasterizedCaption 230 42 34 2 90 84 23 146
eoc
    runTest iptcprint $tmp > $test

    #check results
    diffCheck $test $good
    printf "."
    rm $tmp
}

extendedTest()
{
    src=$1
    tmp="temp"
    test=${src}.ixtst
    good=$datapath/${src}.ixgd

    #setup
    cp $datapath/$src $tmp

    #run tests
    runTest iptctest $tmp < $datapath/ext.dat
    runTest iptcprint $tmp > $test

    #check results
    diffCheck $test $good
    printf "."
    rm $tmp
}

##
#
hardLinkFiles()
{
    target="$1"
    shift
    for var; do
        if [ -e $var ]; then rm -rf $var ; fi
        ln $target $var
    done
}

##
# real_path - report the absolute path to a file
real_path ()
{
    if [ "$PLATFORM" == "Darwin" -o "$PLATFORM" == "mingw" ]; then
        if [ -d "$1" ]; then
            cd "$1"
            echo $PWD
        else
            cd $(dirname $1)
            echo "$PWD"/$(basename "$1")
        fi
    else
        which realpath 2>/dev/null >/dev/null
        if [ $? == 0 ]; then
            realpath "$1"
        else
            readlink -f "$1"
        fi
    fi
}

##
# print checksum for one file
checkSum()
{
    if [ "$PLATFORM" == 'NetBSD' -o "$PLATFORM" == 'FreeBSD' -o "$PLATFORM" == 'Darwin' ]; then
        md5 -q $1
    else
        md5sum $1 | cut -d' ' -f 1
    fi
}

##
# startServer - power up the python web server
startHttpServer() {
    cd "${testdir}/.."                   # testdir is the tmp output directory
    if    [ "$platform" == "platform=cygwin"   ]; then dport=12762
    elif  [ "$platform" == "platform=mingw64"  ]; then dport=12761
    else                                               dport=12760
    fi

    if [ ! -z "$EXIV2_PORT" ]; then port=$EXIV2_PORT ; else port=$dport          ; fi
    if [ ! -z "$EXIV2_HTTP" ]; then http=$EXIV2_HTTP ; else http=http://localhost; fi
    exiv2_url=$http:$port
    python3 -m http.server $port &       # start a background local HTTP server in the "real" test directory
    sleep 2                              # wait for it to init or die!
    exiv2_httpServer=$!
    # ask the server to reply
    echo $exiv2_url status = $(python3 -c "import urllib.request;print(urllib.request.urlopen('$exiv2_url/').status)")
}

##
# closeHttpServer - power down the python web server
closeHttpServer() {
    if [ ! -z $exiv2_httpServer ]; then
        echo kill  exiv2_httpServer $exiv2_httpServer
             kill $exiv2_httpServer      # kill the server
    fi 
}

##
# prepare tmp directory and variables
prepareTest()
{
    ##
    # locale and timezone setting
    export LC_ALL=C
    export TZ=BST-1

    os=$(uname)
    export PLATFORM=$os
    if [ $os != FreeBSD -a $os != NetBSD -a $os != SunOS -a $os != Darwin -a $os != Linux ]; then
        os=$(uname -o)
        if [ $os == Cygwin ]; then
            PLATFORM=cygwin
        elif [ $os == Msys ]; then
            PLATFORM=mingw
        fi
    fi

    if [ "$PLATFORM" == cygwin -o "$PLATFORM" == mingw ]; then
        exe=.exe
    fi

    ##
    # initialize globals
    this=$(basename $0 .sh)
    here=$PWD
    datapath="../data"
    testdir="$here/tmp"
    datadir="../data"

    if [ -z "$EXIV2_BINDIR" ] ; then
        bin="$here/../build/bin/"
    else
        bin="$EXIV2_BINDIR/"
    fi
    
    # update PATHs to ensure we load the the correct dynamlic library
    if [ $PLATFORM == 'mingw' -a $PLATFORM == 'cygwin' ]; then
        export PATH="$bin:$PATH"
    elif [ 'PLATFORM' == 'Darwin' ]; then
        export DYLD_LIBRARY_PATH="$bin/../lib:$DYLD_LIBRARY_PATH"
    else
        export LD_LIBRARY_PATH="$bin/../lib:$LD_LIBRARY_PATH"
    fi

    ##
    # figure out arguments for diff
    good="$here/data/${this}.out"
    results="$here/tmp/${this}.out"
    mkdir -p $here/tmp
    tmpfile=$here/tmp/$this
    echo '' >> $tmpfile

    if [ "$PLATFORM" == SunOS -o "$PLATFORM" == FreeBSD -o "$PLATFORM" == NetBSD ] ; then
        da1=""
        da2=""
    else
        diffargs="--strip-trailing-cr"
        diff -q $diffargs $tmpfile $tmpfile 2>/dev/null
        if [ $? -ne 0 ]; then
            diffargs=""
        fi

        tmpfile=tmp/ttt
        echo '' >> $tmpfile
        da1="--strip-trailing-cr"
        diff -q $da1 $tmpfile $tmpfile 2>/dev/null
        if [ $? -ne 0 ] ; then
            da1=""
        fi
        da2="--ignore-matching-lines=^Usage:.*exiv2"
        diff -q $da2 $tmpfile $tmpfile 2>/dev/null
    fi
    diffargs="$da1 $da2"

    ##
    # test that exiv2 and some sample apps are in the bin!
    for e in exiv2 exifprint easyaccess-test metacopy ; do
        e="${bin}${e}${exe}"
        if [ ! -e "$e" ]; then
            echo '******************************************'
            echo '***' $(real_path "$e") does not exist
            echo '******************************************'
            exit 42
        fi
    done

    # set platform for msvc builds
    platform=$PLATFORM
    if [ $PLATFORM == mingw -o $PLATFORM == cygwin ]; then
        platform=$(runTest exiv2 -vV 2>/dev/null | grep platform=)
        if [ "$platform" == "platform=windows" ]; then
            platform="windows"
        fi
    fi
}

prepareTest

# That's all Folks!
##
